package com.xxx.oauth.server.controller;

import java.net.URISyntaxException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xxx.oauth.server.constant.Constants;
import com.xxx.oauth.server.service.OAuthService;

/**
 * accessToken请求处理 Controller（授权服务器角色）
 */
@RestController
public class AccessTokenController {

    @Autowired
    private OAuthService oAuthService;

    /**
     * 2.请求accessToken
     * @param request
     * @return
     * @throws URISyntaxException
     * @throws OAuthSystemException
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping("/accessToken")
    public HttpEntity accessToken(HttpServletRequest request) throws URISyntaxException, OAuthSystemException {
        try {
            //构建OAuth-Token请求
            OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);

            //1.检查提交的客户端id是否正确（clientId是OAuth-server分配给OAuth-client的）
            if (!oAuthService.checkClientId(oauthRequest.getClientId())) {
                OAuthResponse response = OAuthASResponse
                				.errorResponse(HttpServletResponse.SC_BAD_REQUEST) // 400
                                .setError(OAuthError.TokenResponse.INVALID_CLIENT)
                                .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)
                                .buildJSONMessage();
                return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
            }

            //2.检查客户端安全key是否正确（ClientSecret也是由OAuth-server分配给OAuth-client的）
            if (!oAuthService.checkClientSecret(oauthRequest.getClientSecret())) {
                OAuthResponse response = OAuthASResponse
                				.errorResponse(HttpServletResponse.SC_UNAUTHORIZED) // 401
                                .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
                                .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)
                                .buildJSONMessage();
                return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
            }
            
            
            //3.检查验证类型，此处只检查authorization_code类型，其他的还有password或refresh_token
            String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE); // 上一步中获取到的授权码code
            if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE)   // grant_type==authorization_code?
            		.equals(GrantType.AUTHORIZATION_CODE.toString())) { // 授权模式只接受授权码模式
                if (!oAuthService.checkAuthCode(authCode)) { // 校验授权码不正确
                    OAuthResponse response = OAuthASResponse
                    		.errorResponse(HttpServletResponse.SC_BAD_REQUEST) // 400
                            .setError(OAuthError.TokenResponse.INVALID_GRANT)
                            .setErrorDescription("错误的授权码")
                            .buildJSONMessage();
                    return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
                }
            }

            //4.生成Access Token，并将其放到本地缓存中
            OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
            final String accessToken = oauthIssuerImpl.accessToken();
            //将Access Token放到本地cache里，key为Access Token，value为userName（username放入cache是在上一步创建授权码时进行的）
            oAuthService.addAccessToken(accessToken, oAuthService.getUsernameByAuthCode(authCode));

            //5.生成OAuth-Token响应
            OAuthResponse response = OAuthASResponse
            		.tokenResponse(HttpServletResponse.SC_OK)
                    .setAccessToken(accessToken)
                    .setExpiresIn(String.valueOf(oAuthService.getExpireIn()))
                    .buildJSONMessage();
            //根据OAuthResponse生成ResponseEntity
            return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
        } catch (OAuthProblemException e) { // 异常处理
        	System.err.println(e);
            OAuthResponse res = OAuthASResponse
            		.errorResponse(HttpServletResponse.SC_BAD_REQUEST) // 400
            		.error(e)
                    .buildJSONMessage();
            return new ResponseEntity(res.getBody(), HttpStatus.valueOf(res.getResponseStatus()));
        }
    }

}
